<html>
<head><title>Testing With Visual Web Developer and NUnit</title></head>
<body>
<h1>Testing With Visual Web Developer and NUnit</h1>
<p>
	I am not an Agile evangelist by any means, however, based on my own experience, I've reluctantly conceded that unit testing makes software easier to write. You have a lot more confidence making changes to code when, at any time, you can run the tests to see how if your changes have caused anything to break.
</p>
<p>
	When developers are writing code for FSTDT, I want them to be writing unit tests along the way. And don't get into the mindset of saying, "this change is too small to affect anything, I don't feel like writing a test for this" --- I've been burned dozens of times for making "trivial" changes. Ultimately, all of our unit tests combined should test every line of code in our classes
</p>
<p>
	FSTDT will use NUnit as its unit testing framework. Its free, open source, and I personally found it more user-friendly than other testing frameworks I've used. If you haven't already done so, <a href="http://www.nunit.org/index.php?p=download">download the latest version of NUnit</a>.
</p>

<h2>Testing With Visual Web Developer Isn't Easy</h2>
<p>
	NUnit works pretty much like this: you create a few test classes, then you compile your application into an assembly (an exe or dll), then you open the assembly in Nunit and hit "run tests". The full version of Visual Studio compilies your applications readily into an assembly, it puts the the assembly in a special "bin" folder; you can also precompile web sites by going to the Build menu and clicking the "Publish" option.
</p>
<p>
	Unfortunately, there is no way to pre-compile your website from the Visual Web Developer IDE. You can't run tests in NUnit without an assembly; since Visual Web Developer won't compile an assembly for you, you have to compile it by hand using a command line tool (which comes for free with the .Net framework) called <a href="http://msdn2.microsoft.com/en-us/library/ms229863(VS.80).aspx">aspnet_compiler.exe</a>.
</p>
<p>
	If you don't like compiling by hand, don't worry, I've written a GUI application which executes all of the commandline operations for you. It will let you run NUnit tests for VWD without the hassle of compiling by hand.
</p>

<p>
	With that out of the way, here's how you write tests:
</p>

<h2>Step 1: Add A Reference to the NUnit Framework to Your Website</h2>
<p>
	Open your website in Visual Web Developer.
</p>
<p>
	Find the "Solution Explorer" window. Right click on your project, and click "Add Reference":<br />
	<img src="1.gif" />
</p>
<p>
	A new window will pop up. In the ".Net" tab, scroll down through the list and select the option called "nunit.framework":<br />
	<img src="2.gif" />
</p>
<p>
	Hit OK. A reference to NUnit Now the Nunit framework is created on your website. Visual Web Developer will copy the Nunit dll into your bin folder:<br />
	<img src="3.gif" />
</p>

<h2>Step 2: Write Some Code.</h2>
<p>
	Traditionally, test-driven development emphasizes that you should write your tests before writing your code. I personally don't care what order you write the tests and code in; I usually write my code first, then I write a test to make sure it works.
</p>
<p>
	Since most data access will take place through the data manager classes, I'll create a few tests for one those classes. If you haven't already created a data manager class, <a href="../datamanagertutorial/">this page</a> will show you how to create one.
</p>
<p>
	I'll assume we've already created a Categories tableclass and a Categories rowclass. I'll also assume that our Category class has these properties<br />
- string Name<br />
- string Description<br />
- Category Parent // a reference to another category object<br />
</p>
<p>
	Lets assume our Categories class has the following method:
<pre>
	public static List&lt;Category&gt; GetByParent(Category Parent)
        {
	    Instance.AddParam("ParentID", Parent.ID);
            Instance.AddSort("Name", Sort.Asc);
            return Instance.GetItems();
        }
</pre>
</p>
<p>
	The method is fairly simple: you pass in a Parent category, and you get back list of child categories. Save your changes.
</p>

<h2>Step 3: Make a Test Class</h2>
<p>
	In general, its good to keep related tests together in a single folder. For example, tests related to the FSTDT mainpage and tests related to the forum would go in their own folders. Its also a good practice to create a test class for each manager object you have; for example, you might a testForumsManager.cs, testPublicAdminManager.cs, testMainpageManger.cs, and so on. 
</p>
<p>
	Open the Solution Explorer menu. Expand to the folder App_Code/Tests/. Right click on the folder and click "Add New Folder". Give your folder a better name than the default "New Folder":<br />
	<img src="4.gif" />
</p>
<p>
	After you've created your test folder, you can create a test class. Right click on the folder you've created and choose "Add New Item"<br />
	<img src="5.gif" />
</p>
<p>
	Choose the Class option, and give your class a name:<br />
	<img src="6.gif" />
</p>
<p>
	After you hit OK, the class will show up in your solution manager:<br />
	<img src="7.gif" />
</p>
<p>
	The class will appear in your code editor window. The default class looks like this:
<pre>
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public class testCategories
{
	public testCategories()
	{
		
	}
}
</pre>
</p>
<p>
	To make your code NUnit-compatible, you need to import the NUnit.Framework namespace, and prepend the "[TestFixture]" attribute to your class definition.
<pre>
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
<b>using NUnit.Framework;</b>

<b>[TestFixture]</b>
public class testCategories
{
	public testCategories()
	{
		
	}
}
</pre>

<h2>Step 4: Write A Test</h2>
<p>
	NUnit uses attributes (those things between brackets that appear above certain methods and class definitions) to identify tests. If you aren't familiar with these attributes, or you've never used NUnit before, then read the <a href="http://www.nunit.org/index.php?p=docHome&r=2.4.3">NUnit documentation</a>.
</p>
<p>
	To create a test case, you have to create a public void method which takes 0 parameters. You also have to add the [Test] attribute to the method definition:
<pre>
[TestFixture]
public class testCategories
{
    public testCategories() { }

    [Test]
    public void GetCategoriesByParent()
    {
    }
}
</pre>
</p>

<p>
	Assert something:
<pre>
[TestFixture]
public class testCategories
{
    public testCategories() { }

    [Test]
    public void GetCategoriesByParent()
    {
        Assert.IsTrue(false, "This test will fail.");
    }
}
</pre>
</p>

<p>
	That's it.
</p>

<h2>Step 5: Run Your Tests In NUnit</h2>
<p>
	Since Visual Web Developer doesn't compile assemblies on its own, I wrote a tool called NUnitHelper.exe to assist in the compilation process.
</p>
<p>
	Open the NUnitHelper.exe application:<br />
	<img src="8.gif" />
</p>
<p>
	A folder browse dialog will pop up. Navigate to your FSTDT directory:<br />
	<img src="9.gif" />
</p>
<p>
	Hit ok. You'll see a path to your website in the textbox:<br />
	<img src="10.gif" />
</p>
<p>
	Now click "Compile For NUnit". A couple of things will happen behinds the scenes:
	<ol>
		<li>NUnitHelper will compile your website using the aspnet_compiler.exe tool that comes with the .Net framework 2.0.</li>
		<li>Your website will be copied into a temporary directory (more specifically, it'll copy to the temporary directory listed in the gray box in the window).</li>
		<li>Nunit Helper will attempt to close any instances Nunit already running.</li>
		<li>After the NUnit process exists, NUnit Helper will open a new instance of NUnit and tell NUnit to load the newly compiled assembly.</li>
		<li>A Message will appear in the output boxes indicating whether the compilation was successful.</li>
	</ol>

</p>
<p>
</p>
	NUnitHelper will tell you if there's a problem during compilation. In this example, I have an open connection to my database in the Visual Web Developer IDE.<br />
<img src="11.gif" />
</p>
<p>
	After I closed the connection, everything compiled fine:<br />
	<img src="12.gif" />
</p>
<p>
	You can see the tests that were just added in the NUnit window:<br />
	<img src="13.gif" />
</p>
<p>
	Click the "Run Tests" button to see what's broken:<br />
	<img src="14.gif" />
</p>

<h3>A Note About NUnit Helper</h3>
<p>
	I wrote NUnit Helper to automate the repetive steps needed to compile tests for NUnit. You might notice that the Helper has a peculiar behavior: it closes NUnit, then relaunches it everytime you click "Compile". That behavior is somewhat annoying, but there's no way to avoid it.
</p>
<p>
	When you run your tests, NUnit loads your assembly into memory, then it uses <a href="http://msdn2.microsoft.com/en-us/library/system.reflection.aspx">reflection</a> to find and execute your test methods.
</p>
<p>
	Unfortunately, I've found that NUnit doesn't always release the assembly from memory after the tests have finished running; it also doesn't release resources used by your assembly, such as a connection to SQL Server. You can't recompile your website until NUnit releases its resources; if you try to recompile, you'll get an error along the lines of "such and such process is still in use."
</p>
<p>
	NUnit will release all of the resources its using after it exits; you'll be able to recompile your website at that point. For that reason, I deliberately designed the helper program to close and relaunch NUnit on every recompile.
</p>

<h3>Modifying the Database Safe And OK</h3>
<p>
	I use the aspnet_compiler.exe program to compile websites into NUnit-ready assemblies. Aspnet_Compiler.exe can only compile websites into empty directories; so, I tell it to compile into a temp directory. The temp directory is destroyed and recreated on every recompile; consequently, this means the database is copied into the temp directory over and over.
</p>
<p>
	Since the database is constantly recreated in a temp directory, your don't need to worry about rolling back your changes whenever you write tests that affect the database, your tests will not affect the baseline database. 
</p>
<p>
	Maybe you're the type who likes to rollback changes by default (perhaps because you don't want database changes to affect the state of the database in other tests). If you're using the datamanager (that's a rhetorical "if", you <i>will</i> be using the datamanager), it helps to remember that all datamanager objects use a shared connection object, called DataManagerConnection. You can create begin and rollback transactions in setup/teardown functions like this:
<pre>
private SqlTransaction _trans;

[SetUp]
public void Setup()
{
    _trans = DAL.DataManager.Connection.BeginTransaction();
}

[TearDown]
public void Teardown()
{
    _trans.Rollback();
}
</pre>
</p>

<h3>Configuring the NUnit Helper</h3>
<p>
	By default, NUnit Helper assumes that you have the following files:<br />
- <code>C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_compiler.exe</code><br />
- <code>C:\Program Files\NUnit 2.4.3\bin\nunit.exe</code>
</p>
<p>
	If those programs are insatlled in a different place, open the file <code>NUnitHelper.exe.config</code> (its in the same folder as NunitHelper.exe) and edit the appropriate values. You'll need to restart NuitHelper.exe after you modify its config file.
</p>

<h2>while (tests.failing == true) {fixTests();}</h2>
<p>
	So, after a test fails, you should fix it. Make small, incremental changes to your function, until your test passes. Write some more tests measure the range of expected inputs and outputs; write code until the new tests pass. Continue in that fashion: write a test, write some code, write a test, write some code, write a test, write some code, etc. you're satisifed that your function is thoroughly tested and the tests are passing:<br />
	<img src="15.gif" />
</p>
<p>
	Always run the tests before checking in your changes to the FSTDT repository.
</p>	
</body>
</html>